home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 7 / rzsz0589.zip / RZ.C < prev    next >
C/C++ Source or Header  |  1989-05-25  |  32KB  |  1,543 lines

  1. #define VERSION "3.01 5-25-89"
  2. #define PUBDIR "/usr/spool/uucppublic"
  3.  
  4. /*% cc -compat -M2 -Ox -K -i -DMD % -o rz; size rz;
  5. <-xtx-*> cc386 -Ox -DMD rz.c -o $B/rz;  size $B/rz
  6.  *
  7.  * rz.c By Chuck Forsberg
  8.  *
  9.  *    cc -O rz.c -o rz        USG (3.0) Unix
  10.  *     cc -O -DV7  rz.c -o rz        Unix V7, BSD 2.8 - 4.3
  11.  *
  12.  *    ln rz rb;  ln rz rx            For either system
  13.  *
  14.  *    ln rz /usr/bin/rzrmail        For remote mail.  Make this the
  15.  *                    login shell. rzrmail then calls
  16.  *                    rmail(1) to deliver mail.
  17.  *
  18.  * To compile on VMS:
  19.  *
  20.  *    define LNK$LIBRARY   SYS$LIBRARY:VAXCRTL.OLB
  21.  *    cc rz.c
  22.  *    cc vvmodem.c
  23.  *    link rz,vvmodem
  24.  *    rz :== $disk:[username.subdir]rz.exe
  25.  *      For high speed, try increasing the SYSGEN parameter TTY_TYPAHDSZ to 256.
  26.  *
  27.  *
  28.  *  Unix is a trademark of Western Electric Company
  29.  *
  30.  * A program for Unix to receive files and commands from computers running
  31.  *  Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM.
  32.  *  rz uses Unix buffered input to reduce wasted CPU time.
  33.  *
  34.  *    This version implements ZMODEM Run Length Encoding 
  35.  *    and variable length headers.  These features were not funded
  36.  *    by the original Telenet development contract.  This software,
  37.  *    including these features, may be freely used for non
  38.  *    commercial and educational purposes.  This software may also
  39.  *    be freely used to support file transfer operations to or from
  40.  *    licensed Omen Technology products.  Contact Omen Technology
  41.  *    for licensing for other uses.  Any programs which use part or
  42.  *    all of this software must be provided in source form with this
  43.  *    notice intact except by written permission from Omen
  44.  *    Technology Incorporated.
  45.  *
  46.  *        Omen Technology Inc        FAX: 503-621-3745
  47.  *        Post Office Box 4681
  48.  *        Portland OR 97208
  49.  *
  50.  *    Previous versions of this program (not containing the extensions
  51.  *    listed above) remain in the public domain.
  52.  *
  53.  *    This code is made available in the hope it will be useful,
  54.  *    BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  55.  *    DAMAGES OF ANY KIND.
  56.  *
  57.  *
  58.  * Iff the program is invoked by rzCOMMAND, output is piped to 
  59.  * "COMMAND filename"  (Unix only)
  60.  *
  61.  *  Some systems (Venix, Coherent, Regulus) may not support tty raw mode
  62.  *  read(2) the same way as Unix. ONEREAD must be defined to force one
  63.  *  character reads for these systems. Added 7-01-84 CAF
  64.  *
  65.  *  Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF 
  66.  *
  67.  *  BIX added 6-30-87 to support BIX(TM) upload protocol used by the
  68.  *  Byte Information Exchange.
  69.  *
  70.  *  NFGVMIN Updated 2-18-87 CAF for Xenix systems where c_cc[VMIN]
  71.  *  doesn't work properly (even though it compiles without error!),
  72.  *
  73.  *  SEGMENTS=n added 2-21-88 as a model for CP/M programs
  74.  *    for CP/M-80 systems that cannot overlap modem and disk I/O.
  75.  *
  76.  *  VMS flavor hacks begin with rz version 2.00
  77.  *
  78.  *  -DMD may be added to compiler command line to compile in
  79.  *    Directory-creating routines from Public Domain TAR by John Gilmore
  80.  *
  81.  *  HOWMANY may be tuned for best performance
  82.  *
  83.  *  USG UNIX (3.0) ioctl conventions courtesy  Jeff Martin
  84.  */
  85.  
  86. #ifdef vax11c
  87. #include <types.h>
  88. #include <stat.h>
  89. #define LOGFILE "rzlog.tmp"
  90. #include <stdio.h>
  91. #include <signal.h>
  92. #include <setjmp.h>
  93. #include <ctype.h>
  94. #include <errno.h>
  95. #define OS "VMS"
  96. #define BUFREAD
  97. extern int errno;
  98. #define SS_NORMAL SS$_NORMAL
  99.  
  100. #ifndef PROGNAME
  101. #define PROGNAME "rz"
  102. #endif
  103.  
  104.  
  105. #else
  106.  
  107.  
  108. #define SS_NORMAL 0
  109. #define LOGFILE "/tmp/rzlog"
  110. #include <stdio.h>
  111. #include <signal.h>
  112. #include <setjmp.h>
  113. #include <ctype.h>
  114. #include <errno.h>
  115. extern int errno;
  116. FILE *popen();
  117. #endif
  118.  
  119. #define OK 0
  120. #define FALSE 0
  121. #define TRUE 1
  122. #define ERROR (-1)
  123.  
  124. /*
  125.  * Max value for HOWMANY is 255.
  126.  *   A larger value reduces system overhead but may evoke kernel bugs.
  127.  *   133 corresponds to an XMODEM/CRC sector
  128.  */
  129. #ifndef HOWMANY
  130. #define HOWMANY 133
  131. #endif
  132.  
  133. /* Ward Christensen / CP/M parameters - Don't change these! */
  134. #define ENQ 005
  135. #define CAN ('X'&037)
  136. #define XOFF ('s'&037)
  137. #define XON ('q'&037)
  138. #define SOH 1
  139. #define STX 2
  140. #define EOT 4
  141. #define ACK 6
  142. #define NAK 025
  143. #define CPMEOF 032
  144. #define WANTCRC 0103    /* send C not NAK to get crc not checksum */
  145. #define TIMEOUT (-2)
  146. #define RCDO (-3)
  147. #define GCOUNT (-4)
  148. #define ERRORMAX 5
  149. #define RETRYMAX 5
  150. #define WCEOT (-10)
  151. #define PATHLEN 257    /* ready for 4.2 bsd ? */
  152. #define UNIXFILE 0xF000    /* The S_IFMT file mask bit for stat */
  153.  
  154. int Zmodem=0;        /* ZMODEM protocol requested */
  155. int Nozmodem = 0;    /* If invoked as "rb" */
  156. unsigned Baudrate = 2400;
  157. unsigned Effbaud = 2400;
  158. #ifdef vax11c
  159. #include "vrzsz.c"    /* most of the system dependent stuff here */
  160. #else
  161. #include "rbsb.c"    /* most of the system dependent stuff here */
  162. #endif
  163. #include "crctab.c"
  164.  
  165. char *substr();
  166. FILE *fout;
  167.  
  168. /*
  169.  * Routine to calculate the free bytes on the current file system
  170.  *  ~0 means many free bytes (unknown)
  171.  */
  172. long getfree()
  173. {
  174.     return(~0L);    /* many free bytes ... */
  175. }
  176.  
  177. int Lastrx;
  178. int Crcflg;
  179. int Firstsec;
  180. int Eofseen;        /* indicates cpm eof (^Z) has been received */
  181. int errors;
  182. int Restricted=0;    /* restricted; no /.. or ../ in filenames */
  183. #ifdef ONEREAD
  184. /* Sorry, Regulus and some others don't work right in raw mode! */
  185. int Readnum = 1;    /* Number of bytes to ask for in read() from modem */
  186. #else
  187. int Readnum = HOWMANY;    /* Number of bytes to ask for in read() from modem */
  188. #endif
  189.  
  190. #define DEFBYTL 2000000000L    /* default rx file size */
  191. long Bytesleft;        /* number of bytes of incoming file left */
  192. long Modtime;        /* Unix style mod time for incoming file */
  193. int Filemode;        /* Unix style mode for incoming file */
  194. char Pathname[PATHLEN];
  195. char *Progname;        /* the name by which we were called */
  196.  
  197. int Batch=0;
  198. int Topipe=0;
  199. int MakeLCPathname=TRUE;    /* make received pathname lower case */
  200. int Verbose=0;
  201. int Quiet=0;        /* overrides logic that would otherwise set verbose */
  202. int Nflag = 0;        /* Don't really transfer files */
  203. int Rxclob=FALSE;    /* Clobber existing file */
  204. int Rxbinary=FALSE;    /* receive all files in bin mode */
  205. int Rxascii=FALSE;    /* receive files in ascii (translate) mode */
  206. int Thisbinary;        /* current file is to be received in bin mode */
  207. int Blklen;        /* record length of received packets */
  208.  
  209. #ifdef SEGMENTS
  210. int chinseg = 0;    /* Number of characters received in this data seg */
  211. char secbuf[1+(SEGMENTS+1)*1024];
  212. #else
  213. char secbuf[1025];
  214. #endif
  215.  
  216.  
  217. char linbuf[HOWMANY];
  218. int Lleft=0;        /* number of characters in linbuf */
  219. time_t timep[2];
  220. char Lzmanag;        /* Local file management request */
  221. char zconv;        /* ZMODEM file conversion request */
  222. char zmanag;        /* ZMODEM file management request */
  223. char ztrans;        /* ZMODEM file transport request */
  224. int Zctlesc;        /* Encode control characters */
  225. int Zrwindow = 1400;    /* RX window size (controls garbage count) */
  226.  
  227. jmp_buf tohere;        /* For the interrupt on RX timeout */
  228.  
  229. #define xsendline(c) sendline(c)
  230.  
  231. #include "zm.c"
  232.  
  233. #include "zmr.c"
  234.  
  235. int tryzhdrtype=ZRINIT;    /* Header type to send corresponding to Last rx close */
  236.  
  237. alrm()
  238. {
  239.     longjmp(tohere, -1);
  240. }
  241.  
  242. /* called by signal interrupt or terminate to clean things up */
  243. bibi(n)
  244. {
  245.     if (Zmodem)
  246.         zmputs(Attn);
  247.     canit(); mode(0);
  248.     fprintf(stderr, "rz: caught signal %d; exiting", n);
  249.     cucheck();
  250.     exit(128+n);
  251. }
  252.  
  253. main(argc, argv)
  254. char *argv[];
  255. {
  256.     register char *cp;
  257.     register npats;
  258.     char *virgin, **patts;
  259.     char *getenv();
  260.     int exitcode;
  261.  
  262.     Rxtimeout = 100;
  263.     setbuf(stderr, NULL);
  264.     if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
  265.         Restricted=TRUE;
  266.  
  267.     from_cu();
  268. #ifdef vax11c
  269.     chkinvok(virgin = PROGNAME);
  270. #else
  271.     chkinvok(virgin=argv[0]);    /* if called as [-]rzCOMMAND set flag */
  272. #endif
  273.     npats = 0;
  274.     while (--argc) {
  275.         cp = *++argv;
  276.         if (*cp == '-') {
  277.             while( *++cp) {
  278.                 switch(*cp) {
  279.                 case '\\':
  280.                      cp[1] = toupper(cp[1]);  continue;
  281.                 case '+':
  282.                     Lzmanag = ZMAPND; break;
  283.                 case 'a':
  284.                     Rxascii=TRUE;  break;
  285.                 case 'b':
  286.                     Rxbinary=TRUE; break;
  287.                 case 'c':
  288.                     Crcflg=TRUE; break;
  289. #ifndef vax11c
  290.                 case 'D':
  291.                     Nflag = TRUE; break;
  292. #endif
  293.                 case 'e':
  294.                     Zctlesc = 1; break;
  295.                 case 'p':
  296.                     Lzmanag = ZMPROT;  break;
  297.                 case 'q':
  298.                     Quiet=TRUE; Verbose=0; break;
  299.                 case 't':
  300.                     if (--argc < 1) {
  301.                         usage();
  302.                     }
  303.                     Rxtimeout = atoi(*++argv);
  304.                     if (Rxtimeout<10 || Rxtimeout>1000)
  305.                         usage();
  306.                     break;
  307.                 case 'w':
  308.                     if (--argc < 1) {
  309.                         usage();
  310.                     }
  311.                     Zrwindow = atoi(*++argv);
  312.                     break;
  313.                 case 'u':
  314.                     MakeLCPathname=FALSE; break;
  315.                 case 'v':
  316.                     ++Verbose; break;
  317.                 case 'y':
  318.                     Rxclob=TRUE; break;
  319.                 default:
  320.                     usage();
  321.                 }
  322.             }
  323.         }
  324.         else if ( !npats && argc>0) {
  325.             if (argv[0][0]) {
  326.                 npats=argc;
  327.                 patts=argv;
  328.             }
  329.         }
  330.     }
  331.     if (npats > 1)
  332.         usage();
  333.     if (Batch && npats)
  334.         usage();
  335.     if (Verbose) {
  336.         if (freopen(LOGFILE, "a", stderr)==NULL) {
  337.             printf("Can't open log file %s\n",LOGFILE);
  338.             exit(0200);
  339.         }
  340.         setbuf(stderr, NULL);
  341.         fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
  342.     }
  343.     if (Fromcu && !Quiet) {
  344.         if (Verbose == 0)
  345.             Verbose = 2;
  346.     }
  347.     vfile("%s %s for %s\n", Progname, VERSION, OS);
  348.     mode(1);
  349.     if (signal(SIGINT, bibi) == SIG_IGN) {
  350.         signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
  351.     }
  352.     else {
  353.         signal(SIGINT, bibi); signal(SIGKILL, bibi);
  354.     }
  355.     signal(SIGTERM, bibi);
  356.     if (wcreceive(npats, patts)==ERROR) {
  357.         exitcode=0200;
  358.         canit();
  359.     }
  360.     mode(0);
  361.     if (exitcode && !Zmodem)    /* bellow again with all thy might. */
  362.         canit();
  363.     if (exitcode)
  364.         cucheck();
  365.     exit(exitcode ? exitcode:SS_NORMAL);
  366. }
  367.  
  368.  
  369. usage()
  370. {
  371.     cucheck();
  372.     fprintf(stderr,"Usage:    rz [-abeuvy]        (ZMODEM)\n");
  373.     fprintf(stderr,"or    rb [-abuvy]        (YMODEM)\n");
  374.     fprintf(stderr,"or    rx [-abcv] file    (XMODEM or XMODEM-1k)\n");
  375.     fprintf(stderr,"      -a ASCII transfer (strip CR)\n");
  376.     fprintf(stderr,"      -b Binary transfer for all files\n");
  377. #ifndef vax11c
  378.     fprintf(stderr,"      -c Use 16 bit CRC    (XMODEM)\n");
  379. #endif
  380.     fprintf(stderr,"      -e Escape control characters    (ZMODEM)\n");
  381.     fprintf(stderr,"      -v Verbose more v's give more info\n");
  382.     fprintf(stderr,"      -y Yes, clobber existing file if any\n");
  383.     fprintf(stderr,"%s %s for %s by Chuck Forsberg, Omen Technology INC\n",
  384.       Progname, VERSION, OS);
  385.     fprintf(stderr, "\t\t\042The High Reliability Software\042\n");
  386.     exit(SS_NORMAL);
  387. }
  388. /*
  389.  *  Debugging information output interface routine
  390.  */
  391. /* VARARGS1 */
  392. vfile(f, a, b, c)
  393. register char *f;
  394. {
  395.     if (Verbose > 2) {
  396.         fprintf(stderr, f, a, b, c);
  397.         fprintf(stderr, "\n");
  398.     }
  399. }
  400.  
  401. /*
  402.  * Let's receive something already.
  403.  */
  404.  
  405. char *rbmsg =
  406. "%s ready. To begin transfer, type \"%s file ...\" to your modem program\r\n\n";
  407.  
  408. wcreceive(argc, argp)
  409. char **argp;
  410. {
  411.     register c;
  412.  
  413.     if (Batch || argc==0) {
  414.         Crcflg=1;
  415.         if ( !Quiet)
  416.             fprintf(stderr, rbmsg, Progname, Nozmodem?"sb":"sz");
  417.         if (c=tryz()) {
  418.             if (c == ZCOMPL)
  419.                 return OK;
  420.             if (c == ERROR)
  421.                 goto fubar;
  422.             c = rzfiles();
  423.             if (c)
  424.                 goto fubar;
  425.         } else {
  426.             for (;;) {
  427.                 if (wcrxpn(secbuf)== ERROR)
  428.                     goto fubar;
  429.                 if (secbuf[0]==0)
  430.                     return OK;
  431.                 if (procheader(secbuf) == ERROR)
  432.                     goto fubar;
  433.                 if (wcrx()==ERROR)
  434.                     goto fubar;
  435.             }
  436.         }
  437.     } else {
  438.         Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
  439.  
  440.         procheader(""); strcpy(Pathname, *argp); checkpath(Pathname);
  441.         fprintf(stderr, "\nrz: ready to receive %s\r\n", Pathname);
  442.         if ((fout=fopen(Pathname, "w")) == NULL)
  443.             return ERROR;
  444.         if (wcrx()==ERROR)
  445.             goto fubar;
  446.     }
  447.     return OK;
  448. fubar:
  449.     canit();
  450. #ifndef vax11c
  451.     if (Topipe && fout) {
  452.         pclose(fout);  return ERROR;
  453.     }
  454. #endif
  455.     Modtime = 1;
  456.     if (fout)
  457.         fclose(fout);
  458. #ifndef vax11c
  459.     if (Restricted) {
  460.         unlink(Pathname);
  461.         fprintf(stderr, "\r\nrz: %s removed.\r\n", Pathname);
  462.     }
  463. #endif
  464.     return ERROR;
  465. }
  466.  
  467.  
  468. /*
  469.  * Fetch a pathname from the other end as a C ctyle ASCIZ string.
  470.  * Length is indeterminate as long as less than Blklen
  471.  * A null string represents no more files (YMODEM)
  472.  */
  473. wcrxpn(rpn)
  474. char *rpn;    /* receive a pathname */
  475. {
  476.     register c;
  477.  
  478. #ifdef NFGVMIN
  479.     readline(1);
  480. #else
  481.     purgeline();
  482. #endif
  483.  
  484. et_tu:
  485.     Firstsec=TRUE;  Eofseen=FALSE;
  486.     sendline(Crcflg?WANTCRC:NAK);
  487.     Lleft=0;    /* Do read next time ... */
  488.     while ((c = wcgetsec(rpn, 100)) != 0) {
  489.         if (c == WCEOT) {
  490.             zperr( "Pathname fetch returned %d", c);
  491.             sendline(ACK);
  492.             Lleft=0;    /* Do read next time ... */
  493.             readline(1);
  494.             goto et_tu;
  495.         }
  496.         return ERROR;
  497.     }
  498.     sendline(ACK);
  499.     return OK;
  500. }
  501.  
  502. /*
  503.  * Adapted from CMODEM13.C, written by
  504.  * Jack M. Wierda and Roderick W. Hart
  505.  */
  506.  
  507. wcrx()
  508. {
  509.     register int sectnum, sectcurr;
  510.     register char sendchar;
  511.     register char *p;
  512.     int cblklen;            /* bytes to dump this block */
  513.  
  514.     Firstsec=TRUE;sectnum=0; Eofseen=FALSE;
  515.     sendchar=Crcflg?WANTCRC:NAK;
  516.  
  517.     for (;;) {
  518.         sendline(sendchar);    /* send it now, we're ready! */
  519.         Lleft=0;    /* Do read next time ... */
  520.         sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);
  521.         report(sectcurr);
  522.         if (sectcurr==(sectnum+1 &0377)) {
  523.             sectnum++;
  524.             cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
  525.             if (putsec(secbuf, cblklen)==ERROR)
  526.                 return ERROR;
  527.             if ((Bytesleft-=cblklen) < 0)
  528.                 Bytesleft = 0;
  529.             sendchar=ACK;
  530.         }
  531.         else if (sectcurr==(sectnum&0377)) {
  532.             zperr( "Received dup Sector");
  533.             sendchar=ACK;
  534.         }
  535.         else if (sectcurr==WCEOT) {
  536.             if (closeit())
  537.                 return ERROR;
  538.             sendline(ACK);
  539.             Lleft=0;    /* Do read next time ... */
  540.             return OK;
  541.         }
  542.         else if (sectcurr==ERROR)
  543.             return ERROR;
  544.         else {
  545.             zperr( "Sync Error");
  546.             return ERROR;
  547.         }
  548.     }
  549. }
  550.  
  551. /*
  552.  * Wcgetsec fetches a Ward Christensen type sector.
  553.  * Returns sector number encountered or ERROR if valid sector not received,
  554.  * or CAN CAN received
  555.  * or WCEOT if eot sector
  556.  * time is timeout for first char, set to 4 seconds thereafter
  557.  ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
  558.  *    (Caller must do that when he is good and ready to get next sector)
  559.  */
  560.  
  561. wcgetsec(rxbuf, maxtime)
  562. char *rxbuf;
  563. int maxtime;
  564. {
  565.     register checksum, wcj, firstch;
  566.     register unsigned short oldcrc;
  567.     register char *p;
  568.     int sectcurr;
  569.  
  570.     for (Lastrx=errors=0; errors<RETRYMAX; errors++) {
  571.  
  572.         if ((firstch=readline(maxtime))==STX) {
  573.             Blklen=1024; goto get2;
  574.         }
  575.         if (firstch==SOH) {
  576.             Blklen=128;
  577. get2:
  578.             sectcurr=readline(1);
  579.             if ((sectcurr+(oldcrc=readline(1)))==0377) {
  580.                 oldcrc=checksum=0;
  581.                 for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {
  582.                     if ((firstch=readline(1)) < 0)
  583.                         goto bilge;
  584.                     oldcrc=updcrc(firstch, oldcrc);
  585.                     checksum += (*p++ = firstch);
  586.                 }
  587.                 if ((firstch=readline(1)) < 0)
  588.                     goto bilge;
  589.                 if (Crcflg) {
  590.                     oldcrc=updcrc(firstch, oldcrc);
  591.                     if ((firstch=readline(1)) < 0)
  592.                         goto bilge;
  593.                     oldcrc=updcrc(firstch, oldcrc);
  594.                     if (oldcrc & 0xFFFF)
  595.                         zperr( "CRC");
  596.                     else {
  597.                         Firstsec=FALSE;
  598.                         return sectcurr;
  599.                     }
  600.                 }
  601.                 else if (((checksum-firstch)&0377)==0) {
  602.                     Firstsec=FALSE;
  603.                     return sectcurr;
  604.                 }
  605.                 else
  606.                     zperr( "Checksum");
  607.             }
  608.             else
  609.                 zperr("Sector number garbled");
  610.         }
  611.         /* make sure eot really is eot and not just mixmash */
  612. #ifdef NFGVMIN
  613.         else if (firstch==EOT && readline(1)==TIMEOUT)
  614.             return WCEOT;
  615. #else
  616.         else if (firstch==EOT && Lleft==0)
  617.             return WCEOT;
  618. #endif
  619.         else if (firstch==CAN) {
  620.             if (Lastrx==CAN) {
  621.                 zperr( "Sender CANcelled");
  622.                 return ERROR;
  623.             } else {
  624.                 Lastrx=CAN;
  625.                 continue;
  626.             }
  627.         }
  628.         else if (firstch==TIMEOUT) {
  629.             if (Firstsec)
  630.                 goto humbug;
  631. bilge:
  632.             zperr( "TIMEOUT");
  633.         }
  634.         else
  635.             zperr( "Got 0%o sector header", firstch);
  636.  
  637. humbug:
  638.         Lastrx=0;
  639.         while(readline(1)!=TIMEOUT)
  640.             ;
  641.         if (Firstsec) {
  642.             sendline(Crcflg?WANTCRC:NAK);
  643.             Lleft=0;    /* Do read next time ... */
  644.         } else {
  645.             maxtime=40; sendline(NAK);
  646.             Lleft=0;    /* Do read next time ... */
  647.         }
  648.     }
  649.     /* try to stop the bubble machine. */
  650.     canit();
  651.     return ERROR;
  652. }
  653.  
  654. #ifndef vax11c
  655. /*
  656.  * This version of readline is reasoably well suited for
  657.  * reading many characters.
  658.  *  (except, currently, for the Regulus version!)
  659.  *
  660.  * timeout is in tenths of seconds
  661.  */
  662. readline(timeout)
  663. int timeout;
  664. {
  665.     register n;
  666.     static char *cdq;    /* pointer for removing chars from linbuf */
  667.  
  668.     if (--Lleft >= 0) {
  669.         if (Verbose > 8) {
  670.             fprintf(stderr, "%02x ", *cdq&0377);
  671.         }
  672.         return (*cdq++ & 0377);
  673.     }
  674.     n = timeout/10;
  675.     if (n < 2)
  676.         n = 3;
  677.     if (Verbose > 5)
  678.         fprintf(stderr, "Calling read: alarm=%d  Readnum=%d ",
  679.           n, Readnum);
  680.     if (setjmp(tohere)) {
  681. #ifdef TIOCFLUSH
  682. /*        ioctl(0, TIOCFLUSH, 0); */
  683. #endif
  684.         Lleft = 0;
  685.         if (Verbose>1)
  686.             fprintf(stderr, "Readline:TIMEOUT\n");
  687.         return TIMEOUT;
  688.     }
  689.     signal(SIGALRM, alrm); alarm(n);
  690.     Lleft=read(0, cdq=linbuf, Readnum);
  691.     alarm(0);
  692.     if (Verbose > 5) {
  693.         fprintf(stderr, "Read returned %d bytes\n", Lleft);
  694.     }
  695.     if (Lleft < 1)
  696.         return TIMEOUT;
  697.     --Lleft;
  698.     if (Verbose > 8) {
  699.         fprintf(stderr, "%02x ", *cdq&0377);
  700.     }
  701.     return (*cdq++ & 0377);
  702. }
  703.  
  704.  
  705.  
  706. /*
  707.  * Purge the modem input queue of all characters
  708.  */
  709. purgeline()
  710. {
  711.     Lleft = 0;
  712. #ifdef USG
  713.     ioctl(0, TCFLSH, 0);
  714. #else
  715.     lseek(0, 0L, 2);
  716. #endif
  717. }
  718. #endif
  719.  
  720.  
  721. /*
  722.  * Process incoming file information header
  723.  */
  724. procheader(name)
  725. char *name;
  726. {
  727.     register char *openmode, *p, **pp;
  728.  
  729.     /* set default parameters and overrides */
  730.     openmode = "w";
  731.     Thisbinary = (!Rxascii) || Rxbinary;
  732.     if (Lzmanag)
  733.         zmanag = Lzmanag;
  734.  
  735.     /*
  736.      *  Process ZMODEM remote file management requests
  737.      */
  738.     if (!Rxbinary && zconv == ZCNL)    /* Remote ASCII override */
  739.         Thisbinary = 0;
  740.     if (zconv == ZCBIN)    /* Remote Binary override */
  741.         Thisbinary = TRUE;
  742.     else if (zmanag == ZMAPND)
  743.         openmode = "a";
  744.  
  745. #ifndef BIX
  746.     /* Check for existing file */
  747.     if (!Rxclob && (zmanag&ZMMASK) != ZMCLOB && (fout=fopen(name, "r"))) {
  748.         fclose(fout);  return ERROR;
  749.     }
  750. #endif
  751.  
  752.     Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
  753.  
  754.     p = name + 1 + strlen(name);
  755.     if (*p) {    /* file coming from Unix or DOS system */
  756.         sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode);
  757. #ifndef vax11c
  758.         if (Filemode & UNIXFILE)
  759.             ++Thisbinary;
  760. #endif
  761.         if (Verbose) {
  762.             fprintf(stderr,  "Incoming: %s %ld %lo %o\n",
  763.               name, Bytesleft, Modtime, Filemode);
  764.         }
  765.     }
  766.  
  767. #ifdef BIX
  768.     if ((fout=fopen("scratchpad", openmode)) == NULL)
  769.         return ERROR;
  770.     return OK;
  771. #else
  772.  
  773.     else {        /* File coming from CP/M system */
  774.         for (p=name; *p; ++p)        /* change / to _ */
  775.             if ( *p == '/')
  776.                 *p = '_';
  777.  
  778.         if ( *--p == '.')        /* zap trailing period */
  779.             *p = 0;
  780.     }
  781.  
  782. #ifndef vax11c
  783.     if (!Zmodem && MakeLCPathname && !IsAnyLower(name)
  784.       && !(Filemode&UNIXFILE))
  785.         uncaps(name);
  786. #endif
  787.     if (Topipe > 0) {
  788.         sprintf(Pathname, "%s %s", Progname+2, name);
  789.         if (Verbose)
  790.             fprintf(stderr,  "Topipe: %s %s\n",
  791.               Pathname, Thisbinary?"BIN":"ASCII");
  792. #ifndef vax11c
  793.         if ((fout=popen(Pathname, "w")) == NULL)
  794.             return ERROR;
  795. #endif
  796.     } else {
  797.         strcpy(Pathname, name);
  798.         if (Verbose) {
  799.             fprintf(stderr,  "Receiving %s %s %s\n",
  800.               name, Thisbinary?"BIN":"ASCII", openmode);
  801.         }
  802.         checkpath(name);
  803.         if (Nflag)
  804.             name = "/dev/null";
  805. #ifndef vax11c
  806.         if (name[0] == '!' || name[0] == '|') {
  807.             if ( !(fout = popen(name+1, "w"))) {
  808.                 return ERROR;
  809.             }
  810.             Topipe = -1;  return(OK);
  811.         }
  812. #endif
  813. #ifdef MD
  814.         fout = fopen(name, openmode);
  815.         if ( !fout)
  816.             if (make_dirs(name))
  817.                 fout = fopen(name, openmode);
  818. #else
  819.         fout = fopen(name, openmode);
  820. #endif
  821.         if ( !fout)
  822.             return ERROR;
  823.     }
  824.     return OK;
  825. #endif /* BIX */
  826. }
  827.  
  828. #ifdef MD
  829. /*
  830.  *  Directory-creating routines from Public Domain TAR by John Gilmore
  831.  */
  832.  
  833. /*
  834.  * After a file/link/symlink/dir creation has failed, see if
  835.  * it's because some required directory was not present, and if
  836.  * so, create all required dirs.
  837.  */
  838. make_dirs(pathname)
  839. register char *pathname;
  840. {
  841.     register char *p;        /* Points into path */
  842.     int madeone = 0;        /* Did we do anything yet? */
  843.     int save_errno = errno;        /* Remember caller's errno */
  844.     char *strchr();
  845.  
  846.     if (errno != ENOENT)
  847.         return 0;        /* Not our problem */
  848.  
  849.     for (p = strchr(pathname, '/'); p != NULL; p = strchr(p+1, '/')) {
  850.         /* Avoid mkdir of empty string, if leading or double '/' */
  851.         if (p == pathname || p[-1] == '/')
  852.             continue;
  853.         /* Avoid mkdir where last part of path is '.' */
  854.         if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
  855.             continue;
  856.         *p = 0;                /* Truncate the path there */
  857.         if ( !mkdir(pathname, 0777)) {    /* Try to create it as a dir */
  858.             vfile("Made directory %s\n", pathname);
  859.             madeone++;        /* Remember if we made one */
  860.             *p = '/';
  861.             continue;
  862.         }
  863.         *p = '/';
  864.         if (errno == EEXIST)        /* Directory already exists */
  865.             continue;
  866.         /*
  867.          * Some other error in the mkdir.  We return to the caller.
  868.          */
  869.         break;
  870.     }
  871.     errno = save_errno;        /* Restore caller's errno */
  872.     return madeone;            /* Tell them to retry if we made one */
  873. }
  874.  
  875. #if (MD != 2)
  876. #define    TERM_SIGNAL(status)    ((status) & 0x7F)
  877. #define TERM_COREDUMP(status)    (((status) & 0x80) != 0)
  878. #define TERM_VALUE(status)    ((status) >> 8)
  879. /*
  880.  * Make a directory.  Compatible with the mkdir() system call on 4.2BSD.
  881.  */
  882. mkdir(dpath, dmode)
  883. char *dpath;
  884. int dmode;
  885. {
  886.     int cpid, status;
  887.     struct stat statbuf;
  888.  
  889.     if (stat(dpath,&statbuf) == 0) {
  890.         errno = EEXIST;        /* Stat worked, so it already exists */
  891.         return -1;
  892.     }
  893.  
  894.     /* If stat fails for a reason other than non-existence, return error */
  895.     if (errno != ENOENT) return -1; 
  896.  
  897.     switch (cpid = fork()) {
  898.  
  899.     case -1:            /* Error in fork() */
  900.         return(-1);        /* Errno is set already */
  901.  
  902.     case 0:                /* Child process */
  903.         /*
  904.          * Cheap hack to set mode of new directory.  Since this
  905.          * child process is going away anyway, we zap its umask.
  906.          * FIXME, this won't suffice to set SUID, SGID, etc. on this
  907.          * directory.  Does anybody care?
  908.          */
  909.         status = umask(0);    /* Get current umask */
  910.         status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
  911.         execl("/bin/mkdir", "mkdir", dpath, (char *)0);
  912.         _exit(-1);        /* Can't exec /bin/mkdir */
  913.     
  914.     default:            /* Parent process */
  915.         while (cpid != wait(&status)) ;    /* Wait for kid to finish */
  916.     }
  917.  
  918.     if (TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) {
  919.         errno = EIO;        /* We don't know why, but */
  920.         return -1;        /* /bin/mkdir failed */
  921.     }
  922.  
  923.     return 0;
  924. }
  925. #endif /* MD != 2 */
  926. #endif /* MD */
  927.  
  928. /*
  929.  * Putsec writes the n characters of buf to receive file fout.
  930.  *  If not in binary mode, carriage returns, and all characters
  931.  *  starting with CPMEOF are discarded.
  932.  */
  933. putsec(buf, n)
  934. char *buf;
  935. register n;
  936. {
  937.     register char *p;
  938.  
  939.     if (n == 0)
  940.         return OK;
  941.     if (Thisbinary) {
  942.         for (p=buf; --n>=0; )
  943.             putc( *p++, fout);
  944.     }
  945.     else {
  946.         if (Eofseen)
  947.             return OK;
  948.         for (p=buf; --n>=0; ++p ) {
  949.             if ( *p == '\r')
  950.                 continue;
  951.             if (*p == CPMEOF) {
  952.                 Eofseen=TRUE; return OK;
  953.             }
  954.             putc(*p ,fout);
  955.         }
  956.     }
  957.     return OK;
  958. }
  959.  
  960. #ifndef vax11c
  961. /*
  962.  *  Send a character to modem.  Small is beautiful.
  963.  */
  964. sendline(c)
  965. {
  966.     char d;
  967.  
  968.     d = c;
  969.     if (Verbose>6)
  970.         fprintf(stderr, "Sendline: %x\n", c);
  971.     write(1, &d, 1);
  972. }
  973.  
  974. flushmo() {}
  975. #endif
  976.  
  977.  
  978.  
  979.  
  980.  
  981. /* make string s lower case */
  982. uncaps(s)
  983. register char *s;
  984. {
  985.     for ( ; *s; ++s)
  986.         if (isupper(*s))
  987.             *s = tolower(*s);
  988. }
  989. /*
  990.  * IsAnyLower returns TRUE if string s has lower case letters.
  991.  */
  992. IsAnyLower(s)
  993. register char *s;
  994. {
  995.     for ( ; *s; ++s)
  996.         if (islower(*s))
  997.             return TRUE;
  998.     return FALSE;
  999. }
  1000.  
  1001. /*
  1002.  * substr(string, token) searches for token in string s
  1003.  * returns pointer to token within string if found, NULL otherwise
  1004.  */
  1005. char *
  1006. substr(s, t)
  1007. register char *s,*t;
  1008. {
  1009.     register char *ss,*tt;
  1010.     /* search for first char of token */
  1011.     for (ss=s; *s; s++)
  1012.         if (*s == *t)
  1013.             /* compare token with substring */
  1014.             for (ss=s,tt=t; ;) {
  1015.                 if (*tt == 0)
  1016.                     return s;
  1017.                 if (*ss++ != *tt++)
  1018.                     break;
  1019.             }
  1020.     return NULL;
  1021. }
  1022.  
  1023. /*
  1024.  * Log an error
  1025.  */
  1026. /*VARARGS1*/
  1027. zperr(s,p,u)
  1028. char *s, *p, *u;
  1029. {
  1030.     if (Verbose <= 0)
  1031.         return;
  1032.     fprintf(stderr, "Retry %d: ", errors);
  1033.     fprintf(stderr, s, p, u);
  1034.     fprintf(stderr, "\n");
  1035. }
  1036.  
  1037. /* send cancel string to get the other end to shut up */
  1038. canit()
  1039. {
  1040.     static char canistr[] = {
  1041.      24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
  1042.     };
  1043.  
  1044. #ifdef vax11c
  1045.     raw_wbuf(strlen(canistr), canistr);
  1046.     purgeline();
  1047. #else
  1048.     printf(canistr);
  1049.     Lleft=0;    /* Do read next time ... */
  1050.     fflush(stdout);
  1051. #endif
  1052. }
  1053.  
  1054.  
  1055. report(sct)
  1056. int sct;
  1057. {
  1058.     if (Verbose>1)
  1059.         fprintf(stderr,"%03d%c",sct,sct%10? ' ' : '\r');
  1060. }
  1061.  
  1062. /*
  1063.  * If called as [-][dir/../]vrzCOMMAND set Verbose to 1
  1064.  * If called as [-][dir/../]rzCOMMAND set the pipe flag
  1065.  * If called as rb use YMODEM protocol
  1066.  */
  1067. chkinvok(s)
  1068. char *s;
  1069. {
  1070.     register char *p;
  1071.  
  1072.     p = s;
  1073.     while (*p == '-')
  1074.         s = ++p;
  1075.     while (*p)
  1076.         if (*p++ == '/')
  1077.             s = p;
  1078.     if (*s == 'v') {
  1079.         Verbose=1; ++s;
  1080.     }
  1081.     Progname = s;
  1082.     if (s[0]=='r' && s[1]=='z')
  1083.         Batch = TRUE;
  1084.     if (s[0]=='r' && s[1]=='b')
  1085.         Batch = Nozmodem = TRUE;
  1086.     if (s[2] && s[0]=='r' && s[1]=='b')
  1087.         Topipe = 1;
  1088.     if (s[2] && s[0]=='r' && s[1]=='z')
  1089.         Topipe = 1;
  1090. }
  1091.  
  1092. /*
  1093.  * Totalitarian Communist pathname processing
  1094.  */
  1095. checkpath(name)
  1096. char *name;
  1097. {
  1098.     if (Restricted) {
  1099.         if (fopen(name, "r") != NULL) {
  1100.             canit();
  1101.             fprintf(stderr, "\r\nrz: %s exists\n", name);
  1102.             bibi(-1);
  1103.         }
  1104.         /* restrict pathnames to current tree or uucppublic */
  1105.         if ( substr(name, "../")
  1106.          || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
  1107.             canit();
  1108.             fprintf(stderr,"\r\nrz:\tSecurity Violation\r\n");
  1109.             bibi(-1);
  1110.         }
  1111.     }
  1112. }
  1113.  
  1114. /*
  1115.  * Initialize for Zmodem receive attempt, try to activate Zmodem sender
  1116.  *  Handles ZSINIT frame
  1117.  *  Return ZFILE if Zmodem filename received, -1 on error,
  1118.  *   ZCOMPL if transaction finished,  else 0
  1119.  */
  1120. tryz()
  1121. {
  1122.     register c, n;
  1123.     register cmdzack1flg;
  1124.  
  1125.     if (Nozmodem)        /* Check for "rb" program name */
  1126.         return 0;
  1127.  
  1128.  
  1129.     for (n=Zmodem?15:5; --n>=0; ) {
  1130.         /* Set buffer length (0) and capability flags */
  1131. #ifdef SEGMENTS
  1132.         stohdr(SEGMENTS*1024L);
  1133. #else
  1134.         stohdr(0L);
  1135. #endif
  1136. #ifdef CANBREAK
  1137.         Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
  1138. #else
  1139.         Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
  1140. #endif
  1141.         if (Zctlesc)
  1142.             Txhdr[ZF0] |= TESCCTL;
  1143.         Txhdr[ZF0] |= CANRLE;
  1144.         Txhdr[ZF1] = CANVHDR;
  1145.         /* tryzhdrtype may == ZRINIT */
  1146.         zshhdr(4,tryzhdrtype, Txhdr);
  1147.         if (tryzhdrtype == ZSKIP)    /* Don't skip too far */
  1148.             tryzhdrtype = ZRINIT;    /* CAF 8-21-87 */
  1149. again:
  1150.         switch (zgethdr(Rxhdr, 0)) {
  1151.         case ZRQINIT:
  1152.             if (Rxhdr[ZF3] & 0x80)
  1153.                 Usevhdrs = 1;    /* we can var header */
  1154.             continue;
  1155.         case ZEOF:
  1156.             continue;
  1157.         case TIMEOUT:
  1158.             continue;
  1159.         case ZFILE:
  1160.             zconv = Rxhdr[ZF0];
  1161.             zmanag = Rxhdr[ZF1];
  1162.             ztrans = Rxhdr[ZF2];
  1163.             if (Rxhdr[ZF3] & ZCANVHDR)
  1164.                 Usevhdrs = TRUE;
  1165.             tryzhdrtype = ZRINIT;
  1166.             c = zrdata(secbuf, 1024);
  1167.             mode(3);
  1168.             if (c == GOTCRCW)
  1169.                 return ZFILE;
  1170.             zshhdr(4,ZNAK, Txhdr);
  1171.             goto again;
  1172.         case ZSINIT:
  1173.             Zctlesc = TESCCTL & Rxhdr[ZF0];
  1174.             if (zrdata(Attn, ZATTNLEN) == GOTCRCW) {
  1175.                 stohdr(1L);
  1176.                 zshhdr(4,ZACK, Txhdr);
  1177.                 goto again;
  1178.             }
  1179.             zshhdr(4,ZNAK, Txhdr);
  1180.             goto again;
  1181.         case ZFREECNT:
  1182.             stohdr(getfree());
  1183.             zshhdr(4,ZACK, Txhdr);
  1184.             goto again;
  1185.         case ZCOMMAND:
  1186. #ifdef vax11c
  1187.             return ERROR;
  1188. #else
  1189.             cmdzack1flg = Rxhdr[ZF0];
  1190.             if (zrdata(secbuf, 1024) == GOTCRCW) {
  1191.                 if (cmdzack1flg & ZCACK1)
  1192.                     stohdr(0L);
  1193.                 else
  1194.                     stohdr((long)sys2(secbuf));
  1195.                 purgeline();    /* dump impatient questions */
  1196.                 do {
  1197.                     zshhdr(4,ZCOMPL, Txhdr);
  1198.                 }
  1199.                 while (++errors<20 && zgethdr(Rxhdr,1) != ZFIN);
  1200.                 ackbibi();
  1201.                 if (cmdzack1flg & ZCACK1)
  1202.                     exec2(secbuf);
  1203.                 return ZCOMPL;
  1204.             }
  1205.             zshhdr(4,ZNAK, Txhdr); goto again;
  1206. #endif
  1207.         case ZCOMPL:
  1208.             goto again;
  1209.         default:
  1210.             continue;
  1211.         case ZFIN:
  1212.             ackbibi(); return ZCOMPL;
  1213.         case ZCAN:
  1214.             return ERROR;
  1215.         }
  1216.     }
  1217.     return 0;
  1218. }
  1219.  
  1220. /*
  1221.  * Receive 1 or more files with ZMODEM protocol
  1222.  */
  1223. rzfiles()
  1224. {
  1225.     register c;
  1226.  
  1227.     for (;;) {
  1228.         switch (c = rzfile()) {
  1229.         case ZEOF:
  1230.         case ZSKIP:
  1231.             switch (tryz()) {
  1232.             case ZCOMPL:
  1233.                 return OK;
  1234.             default:
  1235.                 return ERROR;
  1236.             case ZFILE:
  1237.                 break;
  1238.             }
  1239.             continue;
  1240.         default:
  1241.             return c;
  1242.         case ERROR:
  1243.             return ERROR;
  1244.         }
  1245.     }
  1246. }
  1247.  
  1248. /*
  1249.  * Receive a file with ZMODEM protocol
  1250.  *  Assumes file name frame is in secbuf
  1251.  */
  1252. rzfile()
  1253. {
  1254.     register c, n;
  1255.     long rxbytes;
  1256.  
  1257.     Eofseen=FALSE;
  1258.     if (procheader(secbuf) == ERROR) {
  1259.         return (tryzhdrtype = ZSKIP);
  1260.     }
  1261.  
  1262.     n = 20; rxbytes = 0l;
  1263.  
  1264.     for (;;) {
  1265. #ifdef SEGMENTS
  1266.         chinseg = 0;
  1267. #endif
  1268.         stohdr(rxbytes);
  1269.         zshhdr(4,ZRPOS, Txhdr);
  1270. nxthdr:
  1271.         switch (c = zgethdr(Rxhdr, 0)) {
  1272.         default:
  1273.             vfile("rzfile: zgethdr returned %d", c);
  1274.             return ERROR;
  1275.         case ZNAK:
  1276.         case TIMEOUT:
  1277. #ifdef SEGMENTS
  1278.             putsec(secbuf, chinseg);
  1279.             chinseg = 0;
  1280. #endif
  1281.             if ( --n < 0) {
  1282.                 vfile("rzfile: zgethdr returned %d", c);
  1283.                 return ERROR;
  1284.             }
  1285.         case ZFILE:
  1286.             zrdata(secbuf, 1024);
  1287.             continue;
  1288.         case ZEOF:
  1289. #ifdef SEGMENTS
  1290.             putsec(secbuf, chinseg);
  1291.             chinseg = 0;
  1292. #endif
  1293.             if (rclhdr(Rxhdr) != rxbytes) {
  1294.                 /*
  1295.                  * Ignore eof if it's at wrong place - force
  1296.                  *  a timeout because the eof might have gone
  1297.                  *  out before we sent our zrpos.
  1298.                  */
  1299.                 errors = 0;  goto nxthdr;
  1300.             }
  1301.             if (closeit()) {
  1302.                 tryzhdrtype = ZFERR;
  1303.                 vfile("rzfile: closeit returned <> 0");
  1304.                 return ERROR;
  1305.             }
  1306.             vfile("rzfile: normal EOF");
  1307.             return c;
  1308.         case ERROR:    /* Too much garbage in header search error */
  1309. #ifdef SEGMENTS
  1310.             putsec(secbuf, chinseg);
  1311.             chinseg = 0;
  1312. #endif
  1313.             if ( --n < 0) {
  1314.                 vfile("rzfile: zgethdr returned %d", c);
  1315.                 return ERROR;
  1316.             }
  1317.             zmputs(Attn);
  1318.             continue;
  1319.         case ZSKIP:
  1320. #ifdef SEGMENTS
  1321.             putsec(secbuf, chinseg);
  1322.             chinseg = 0;
  1323. #endif
  1324.             Modtime = 1;
  1325.             closeit();
  1326.             vfile("rzfile: Sender SKIPPED file");
  1327.             return c;
  1328.         case ZDATA:
  1329.             if (rclhdr(Rxhdr) != rxbytes) {
  1330.                 if ( --n < 0) {
  1331.                     return ERROR;
  1332.                 }
  1333. #ifdef SEGMENTS
  1334.                 putsec(secbuf, chinseg);
  1335.                 chinseg = 0;
  1336. #endif
  1337.                 zmputs(Attn);  continue;
  1338.             }
  1339. moredata:
  1340.             if (Verbose>1)
  1341.                 fprintf(stderr, "\r%7ld ZMODEM%s    ",
  1342.                   rxbytes, Crc32r?" CRC-32":"");
  1343. #ifdef SEGMENTS
  1344.             if (chinseg >= (1024 * SEGMENTS)) {
  1345.                 putsec(secbuf, chinseg);
  1346.                 chinseg = 0;
  1347.             }
  1348.             switch (c = zrdata(secbuf+chinseg, 1024))
  1349. #else
  1350.             switch (c = zrdata(secbuf, 1024))
  1351. #endif
  1352.             {
  1353.             case ZCAN:
  1354. #ifdef SEGMENTS
  1355.                 putsec(secbuf, chinseg);
  1356.                 chinseg = 0;
  1357. #endif
  1358.                 vfile("rzfile: zgethdr returned %d", c);
  1359.                 return ERROR;
  1360.             case ERROR:    /* CRC error */
  1361. #ifdef SEGMENTS
  1362.                 putsec(secbuf, chinseg);
  1363.                 chinseg = 0;
  1364. #endif
  1365.                 if ( --n < 0) {
  1366.                     vfile("rzfile: zgethdr returned %d", c);
  1367.                     return ERROR;
  1368.                 }
  1369.                 zmputs(Attn);
  1370.                 continue;
  1371.             case TIMEOUT:
  1372. #ifdef SEGMENTS
  1373.                 putsec(secbuf, chinseg);
  1374.                 chinseg = 0;
  1375. #endif
  1376.                 if ( --n < 0) {
  1377.                     vfile("rzfile: zgethdr returned %d", c);
  1378.                     return ERROR;
  1379.                 }
  1380.                 continue;
  1381.             case GOTCRCW:
  1382.                 n = 20;
  1383. #ifdef SEGMENTS
  1384.                 chinseg += Rxcount;
  1385.                 putsec(secbuf, chinseg);
  1386.                 chinseg = 0;
  1387. #else
  1388.                 putsec(secbuf, Rxcount);
  1389. #endif
  1390.                 rxbytes += Rxcount;
  1391.                 stohdr(rxbytes);
  1392.                 zshhdr(4,ZACK, Txhdr);
  1393.                 sendline(XON);
  1394.                 goto nxthdr;
  1395.             case GOTCRCQ:
  1396.                 n = 20;
  1397. #ifdef SEGMENTS
  1398.                 chinseg += Rxcount;
  1399. #else
  1400.                 putsec(secbuf, Rxcount);
  1401. #endif
  1402.                 rxbytes += Rxcount;
  1403.                 stohdr(rxbytes);
  1404.                 zshhdr(4,ZACK, Txhdr);
  1405.                 goto moredata;
  1406.             case GOTCRCG:
  1407.                 n = 20;
  1408. #ifdef SEGMENTS
  1409.                 chinseg += Rxcount;
  1410. #else
  1411.                 putsec(secbuf, Rxcount);
  1412. #endif
  1413.                 rxbytes += Rxcount;
  1414.                 goto moredata;
  1415.             case GOTCRCE:
  1416.                 n = 20;
  1417. #ifdef SEGMENTS
  1418.                 chinseg += Rxcount;
  1419. #else
  1420.                 putsec(secbuf, Rxcount);
  1421. #endif
  1422.                 rxbytes += Rxcount;
  1423.                 goto nxthdr;
  1424.             }
  1425.         }
  1426.     }
  1427. }
  1428.  
  1429. /*
  1430.  * Send a string to the modem, processing for \336 (sleep 1 sec)
  1431.  *   and \335 (break signal)
  1432.  */
  1433. zmputs(s)
  1434. char *s;
  1435. {
  1436.     register c;
  1437.  
  1438.     while (*s) {
  1439.         switch (c = *s++) {
  1440.         case '\336':
  1441.             sleep(1); continue;
  1442.         case '\335':
  1443.             sendbrk(); continue;
  1444.         default:
  1445.             sendline(c);
  1446.         }
  1447.     }
  1448. }
  1449.  
  1450. /*
  1451.  * Close the receive dataset, return OK or ERROR
  1452.  */
  1453. closeit()
  1454. {
  1455.     time_t time();
  1456.  
  1457. #ifndef vax11c
  1458.     if (Topipe) {
  1459.         if (pclose(fout)) {
  1460.             return ERROR;
  1461.         }
  1462.         return OK;
  1463.     }
  1464. #endif
  1465.     if (fclose(fout)==ERROR) {
  1466.         fprintf(stderr, "file close ERROR\n");
  1467.         return ERROR;
  1468.     }
  1469. #ifndef vax11c
  1470.     if (Modtime) {
  1471.         timep[0] = time(NULL);
  1472.         timep[1] = Modtime;
  1473.         utime(Pathname, timep);
  1474.     }
  1475. #endif
  1476.     if ((Filemode&S_IFMT) == S_IFREG)
  1477.         chmod(Pathname, (07777 & Filemode));
  1478.     return OK;
  1479. }
  1480.  
  1481. /*
  1482.  * Ack a ZFIN packet, let byegones be byegones
  1483.  */
  1484. ackbibi()
  1485. {
  1486.     register n;
  1487.  
  1488.     vfile("ackbibi:");
  1489.     Readnum = 1;
  1490.     stohdr(0L);
  1491.     for (n=3; --n>=0; ) {
  1492.         purgeline();
  1493.         zshhdr(4,ZFIN, Txhdr);
  1494.         switch (readline(100)) {
  1495.         case 'O':
  1496.             readline(1);    /* Discard 2nd 'O' */
  1497.             vfile("ackbibi complete");
  1498.             return;
  1499.         case RCDO:
  1500.             return;
  1501.         case TIMEOUT:
  1502.         default:
  1503.             break;
  1504.         }
  1505.     }
  1506. }
  1507.  
  1508.  
  1509.  
  1510. /*
  1511.  * Local console output simulation
  1512.  */
  1513. bttyout(c)
  1514. {
  1515.     if (Verbose || Fromcu)
  1516.         putc(c, stderr);
  1517. }
  1518.  
  1519. #ifndef vax11c
  1520. /*
  1521.  * Strip leading ! if present, do shell escape. 
  1522.  */
  1523. sys2(s)
  1524. register char *s;
  1525. {
  1526.     if (*s == '!')
  1527.         ++s;
  1528.     return system(s);
  1529. }
  1530. /*
  1531.  * Strip leading ! if present, do exec.
  1532.  */
  1533. exec2(s)
  1534. register char *s;
  1535. {
  1536.     if (*s == '!')
  1537.         ++s;
  1538.     mode(0);
  1539.     execl("/bin/sh", "sh", "-c", s);
  1540. }
  1541. #endif
  1542. /* End of rz.c */
  1543.